#ifndef RTPPARSE_NACK_GENERATOR_H
#define RTPPARSE_NACK_GENERATOR_H

#include "rtp/RtpPacket.h"
#include "rtp/SeqManager.h"
#include "TimerHandle.h"

#include <map>
#include <set>
#include <vector>

/**
 * NackGenerator 
 * 专门用于处理接收端的丢包恢复请求
 * 
 */

namespace Rtp {
    class NackGenerator : public TimerHandle::Listener {
    public:
        class Listener {
        public:
            virtual ~Listener() = default;
        public:
            virtual void OnNackGeneratorNackRequired(const std::vector<uint16_t>& seqNumbers) = 0;
            virtual void OnNackGeneratorKeyFrameRequired() = 0;
        };
    private:
        struct NackInfo {
            NackInfo() = default;
            explicit NackInfo(uint64_t createdAtMs, uint16_t seq, uint16_t sendAtSeq):createdAtMs(createdAtMs),seq(seq), sendAtSeq(sendAtSeq){}

            uint64_t createdAtMs { 0u }; // When this NACK was created.
            uint16_t seq { 0u };        // Sequence number of the NACK.
            uint16_t sendAtSeq { 0u };  // Sequence number at which this
            uint64_t sendAtMs { 0u }; // When this NACK was sent.
            uint8_t retries { 0u };
        };

        enum class NackFilter {
            SEQ,
            TIME
        };
    public:
        explicit NackGenerator(Listener *listener, unsigned int sendNackDelayMs);
        ~NackGenerator() override;

        bool ReceivePacket(Rtp::RtpPacket* packet, bool isRecovered);

        size_t GetNackListLength() const {
            return this->nackList.size();
        }

        void UpdateRtt(uint32_t rtt) {
            this->rtt = rtt;
        }

        void Reset();
    private:
        void AddPacketsToNackList(uint16_t seqStart, uint16_t seqEnd);
        bool RemoveNackItemsUntilKeyFrame();
        std::vector<uint16_t> GetNackBatch(NackFilter filter);
        void MayRunTimer() const;

    public:
        void OnTimer(TimerHandle *timer) override;

    private:
        Listener* listener { nullptr };
        unsigned int sendNackDelayMs { 0u };
        TimerHandle* timer { nullptr };

        std::map<uint16_t, NackInfo, Rtp::SeqManager<uint16_t>::SeqLowerThan> nackList; // NACK list. 
        std::set<uint16_t, Rtp::SeqManager<uint16_t>::SeqLowerThan> keyFrameList; // Key frame list.
        std::set<uint16_t, Rtp::SeqManager<uint16_t>::SeqLowerThan> recoveredList;

        bool started { false };
        uint16_t lastSeq { 0u }; // Seq number of last valid packet.
        uint32_t rtt { 0u }; // Round Trip Time in milliseconds.
    };
}

#endif